package cn.luckdou.system.controller.order;

import java.io.BufferedReader;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.luckdou.commons.pay.alipay.config.AlipayConfig;
import cn.luckdou.commons.pay.alipay.pojo.AlipaySyntony;
import cn.luckdou.commons.pay.alipay.util.AlipayNotify;
import cn.luckdou.commons.pay.wechat.WXPayResult;
import cn.luckdou.commons.pay.wechat.WechatUtil;
import cn.luckdou.commons.pay.wechat.util.WXSignUtils;
import cn.luckdou.commons.pay.wechat.util.UnifiedorderResult;
import cn.luckdou.commons.pay.wechat.util.XmlJsonUtil;
import cn.luckdou.commons.utils.JsonUtils;
import cn.luckdou.system.controller.vo.WxCreateVo;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import cn.luckdou.commons.base.BaseController;
import cn.luckdou.commons.utils.Des3Util;
import cn.luckdou.commons.utils.IDUtils;

@Controller
@RequestMapping("/app/pay")
public class AlipayWeChatController extends BaseController {
	private Logger logger = Logger.getLogger(this.getClass());

	@PostMapping(value = "/createOrder")
	@ResponseBody
	public Object addOrder(String json) throws Exception {
		try {
			if (StringUtils.isBlank(json)) {
				return renderError("参数不能为空");
			}
			json = Des3Util.decode(json);
			WxCreateVo pay = JsonUtils.jsonToPojo(json, WxCreateVo.class);
			if (pay != null && pay.getUserId() != null && pay.getAmount() != null
					&& StringUtils.isNotBlank(pay.getFlag())) {
				if (pay.getAmount() < 1) {
					return renderError("最低金额¥ 1");
				}
				if (pay.getPayType().equals("wx")) {
					UnifiedorderResult unifiedorderResult = WechatUtil.preOrder(IDUtils.getOrderNum(), 1);
					return renderSuccess(Des3Util.encode(JsonUtils.objectToJson(unifiedorderResult)));
				} else if (pay.getPayType().equals("alipay")) {
					return app_alipay(IDUtils.getOrderNum(), "0.01");
				}
			}
		} catch (Exception e) {
			return renderError("参数错误");
		}
		return renderError("参数不能为空");
	}

	private Object app_alipay(String outTradeNo, String totalAmount) throws Exception {
		// 实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
				AlipayConfig.partner, AlipayConfig.private_key, "json", AlipayConfig.input_charset,
				AlipayConfig.ali_public_key, "RSA2");
		// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
		// SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
		model.setBody("partylive 充值金币");
		model.setSubject("partylive 充值金币" + totalAmount);
		model.setOutTradeNo(outTradeNo);
		model.setTimeoutExpress("30m");
		model.setTotalAmount(totalAmount);
		model.setProductCode("QUICK_MSECURITY_PAY");
		request.setBizModel(model);
		request.setNotifyUrl("http://192.168.0.4:8082/app/pay/createOrder");
		try {
			// 这里和普通的接口调用不同，使用的是sdkExecute
			AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
			System.out.println(response.getBody());// 就是orderString 可以直接给客户端请求，无需再做处理。
			String encode = Des3Util.encode(JsonUtils.objectToJson(response.getBody()));
			return renderSuccess(encode);
		} catch (AlipayApiException e) {
			e.printStackTrace();
			return renderError("生成订单错误");
		}
	}


	/**
	 * 微信支付回调
	 * 
	 * @param request
	 */
	@RequestMapping(value = "/wx_notify_url")
	public void notifyWeixinPayment(HttpServletRequest request, HttpServletResponse response) {
		try {
			BufferedReader reader = request.getReader();
			String line = "";
			StringBuffer inputString = new StringBuffer();
			try {
				PrintWriter writer = response.getWriter();
				while ((line = reader.readLine()) != null) {
					inputString.append(line);
				}
				if (reader != null) {
					reader.close();
				}
				if (!StringUtils.isEmpty(inputString.toString())) {
					String json = XmlJsonUtil.xml2JSON(inputString.toString());
					// logger.info("微信支付:"+json);
					WXPayResult wxPayResult = JsonUtils.jsonToPojo(json, WXPayResult.class);
					if (wxPayResult.getReturn_code().toLowerCase().contains("SUCCESS".toLowerCase())) {
						SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
						parameters.put("appid", wxPayResult.getAppid());
						parameters.put("attach", wxPayResult.getAttach());
						parameters.put("bank_type", wxPayResult.getBank_type());
						parameters.put("cash_fee", wxPayResult.getCash_fee());
						parameters.put("fee_type", wxPayResult.getFee_type());
						parameters.put("is_subscribe", wxPayResult.getIs_subscribe());
						parameters.put("mch_id", wxPayResult.getMch_id());
						parameters.put("nonce_str", wxPayResult.getNonce_str());
						parameters.put("openid", wxPayResult.getOpenid());
						parameters.put("out_trade_no", wxPayResult.getOut_trade_no());
						parameters.put("result_code", wxPayResult.getResult_code());
						parameters.put("return_code", wxPayResult.getReturn_code());
						parameters.put("time_end", wxPayResult.getTime_end());
						parameters.put("total_fee", wxPayResult.getTotal_fee());
						parameters.put("trade_type", wxPayResult.getTrade_type());
						parameters.put("transaction_id", wxPayResult.getTransaction_id());
						// 反校验签名
						String sign = WXSignUtils.createSign("UTF-8", parameters);
						if (wxPayResult.getResult_code().equals("SUCCESS") && sign.equals(wxPayResult.getSign())) {

						} else {
							writer.write(setXml("FAIL", "签名失败"));
						}
					} else {
						writer.write(setXml("FAIL", wxPayResult.getReturn_msg()));
						logger.info("---------微信支付返回Fail----------" + wxPayResult.getReturn_msg());
					}
					if (writer != null) {
						writer.close();
					}
				} else {
					writer.write(setXml("FAIL", "未获取到微信返回的结果"));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * 支付宝回调
	 * <p>Title: pay_url</p>
	 * <p>Description: </p>
	 *  @author Dadou
	 *  @DateTime 2017年7月13日 上午11:01:42
	 *  @param notify
	 *  @param total_fee
	 *  @param request
	 *  @param response
	 *  @throws Exception
	 */
	@RequestMapping(value = "/notify_url", method = RequestMethod.POST)
	public void pay_url(AlipaySyntony notify, @RequestParam(defaultValue = "0.00") double total_fee,
                        HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 获取支付宝POST过来反馈信息
		Map<String, String> params = new HashMap<String, String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}
		logger.info("收到支付宝异步回调 参数：" + params.toString());
		logger.info("收到支付宝异步回调对象：" + JsonUtils.objectToJson(notify));
		ServletOutputStream out = response.getOutputStream();
		// 1.务必要判断验证签名及notify_id合法性校验
		if (AlipayNotify.verify(params)) {// 验证成功
			logger.info("支付宝验证成功");
			out.print("success");
			return;
			// 4）主动回调模式的页面文件中，success是否有成功打印且没有其他信息
		} else {// 验证失败
			logger.info("支付宝验证失败:fail");
			out.print("fail");
			return;
		}

	}

	public static String setXml(String return_code, String return_msg) {
		return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg
				+ "]]></return_msg></xml>";
	}
}
